#ifndef __CLOGING_H__
#define __CLOGING_H__

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#ifdef __cplusplus
extern "C" {
#endif

#define CLOG_LIB_NAME "libclog.so"

/* #define CLOG_NDEBUG 1 */
#define STDOUT_ENABLE 1
#define CLOG_BUF_SIZE 1024
#define CLOG_TAG_SIZE 16

#ifndef LOG_TAG
#define LOG_TAG "unknown"
#endif

/* get log level from environment variable */
#define LOGLEVEL_ENV	"LOGLEVEL"

#define CLOG_DEFAULT_LEVEL CLOG_ERROR

#ifndef pr_fmt
#define pr_fmt(fmt) "[%s:%d] " fmt, __FILE__, __LINE__
#endif

typedef struct {
    int (*clog_log_write_p)(int prio, const char* tag, const char* log_buf);
    pthread_once_t init_once;
    pthread_t consumer_thread;
    int thread_running;
} clog_global_state_t;

extern clog_global_state_t g_clog_global_state;

typedef enum {
	CLOG_UNKNOWN = 0,
	CLOG_VERBOSE,
	CLOG_DEBUG,
	CLOG_INFO,
	CLOG_WARN,
	CLOG_ERROR,
	CLOG_FATAL,
    CLOG_MAX,
} clog_priority_e;

typedef struct {
	int32_t prio;
	int32_t pid;
	int32_t ppid;
	time_t tv_sec;
	long tv_nsec;
	char tag[CLOG_TAG_SIZE];
	size_t message_len;
	char message[CLOG_BUF_SIZE];
} clog_entry_t;

// int _clog_log_print(int prio, const char* tag, const char* fmt, ...);
#define __CLOG_LOG(prio, tag, fmt, ...) _clog_log_print(prio, tag, pr_fmt(fmt), ##__VA_ARGS__)

/* print verbose log */
#define pr_verbose(fmt, ...) __CLOG_LOG(CLOG_VERBOSE, LOG_TAG, fmt, ##__VA_ARGS__)
#define pr_debug(fmt, ...)   __CLOG_LOG(CLOG_DEBUG,   LOG_TAG, fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...)    __CLOG_LOG(CLOG_INFO,    LOG_TAG, fmt, ##__VA_ARGS__)
#define pr_warn(fmt, ...)    __CLOG_LOG(CLOG_WARN,    LOG_TAG, fmt, ##__VA_ARGS__)
#define pr_error(fmt, ...)   __CLOG_LOG(CLOG_ERROR,   LOG_TAG, fmt, ##__VA_ARGS__)
#define pr_fatal(fmt, ...)   __CLOG_LOG(CLOG_FATAL,   LOG_TAG, fmt, ##__VA_ARGS__)

static int __clog_write_init(int prio, const char* tag, const char* log_buf);

#endif /* __CLOGING_H__ */
